#define _GNU_SOURCE
#include "app_bt.h"
#include "string.h"
#include "log/log.h"
#include "unistd.h"
#include "app_serial.h"

char read_buf[1024];
int read_len = 0; //已经读取的数据长度
char head_frame[2] = {0xf1, 0xdd};


static void remove_data(int len)
{
    memmove(read_buf , read_buf + len, read_len - len);
    read_len -= len;
}

static int wait_ack(int fd)
{   
    usleep(50 * 1000);

    char data_buf[4];

    int ret = read(fd, data_buf, 4);

    if(ret < 0)
    {
        log_error("read error");
        return -1;
    }

    if(memcmp(data_buf, "OK\r\n", 4) != 0)
    {
        log_error("wait_ack error");
        return -1;
    }
    
    return 0;
}

static int init_bt_config(Device_t *device) {
    // 初始化串口
    app_serial_init(device);
    // 将串口设置为非阻塞模式
    app_serial_setBlock(device, 0);
    app_serial_flush(device);


    // 1. 先修改BT（需要通信）
    // 2. 修改串口波特率

    // 判断如果蓝牙可用 =》 说明当前蓝牙波特率还9600 =》 设置蓝牙波特率为115200， 设置NETID/MAddr 并重启蓝牙
    if (app_bt_status(device)==0) {
        app_bt_setBaudRate(device, BT_BR_115200);  // 设置蓝牙波特率为115200
        app_bt_setNetid(device, "0a0b"); // 设置蓝牙的NETID
        app_bt_setMaddr(device, "0102"); // 设置蓝牙的MADDR
        app_bt_rename(device, "atguigu"); // 设置蓝牙名称

        app_bt_reset(device); // 重启蓝牙
        // 等待蓝牙重启完成
        sleep(2);
    }

    // 修改串口波特率为115200
    app_serial_setBaudRate(device, BR_115200);
    app_serial_flush(device);

    // 检查蓝牙是否可用，如果不可用，说明蓝牙初始化失败
    if (app_bt_status(device) != 0) {
        log_debug("蓝牙初始化失败");
        return -1;
    }

    // 将串口改为阻塞模式
    app_serial_setBlock(device, 1);
    app_serial_flush(device);

    log_debug("蓝牙初始化成功");
    return 0;
}

void app_bt_init(Device_t *device)
{
    device->pre_write = app_bt_preWrite;
    device->post_read = app_bt_postRead;

    return init_bt_config(device);
}

/*
字符数组消息: 
    例子：1 2 3 XX abc
    格式：conn_type id_len msg_len id msg
蓝牙发送数据格式例子：41 54 2b 4d 45 53 48 00 ff ff 61 62 63 0d 0a
    例子：
    41 54 2b 4d 45 53 48 00： AT+MESH（固定头部）
    ff ff: 对端的MADDR（如果是FFFF代表群发）
    61 62 63: 要发送的数据（不超过12字节）
    0d 0a：\r\n（固定结尾）
    AT+MESH XX abc \r\n
*/
int app_bt_preWrite(char *data, int len)
{
    // 检查data的长度
    if (len < 6) {
        log_error("字符数组消息长度不能小于6");
        return -1;
    }

    int data_len = 0;
    data_len = 8 + 2 + data[2] +2;
    char data_buf[data_len];

    memcpy(data_buf, "AT+MESH" , 8);
    memcpy(data_buf + 8, data+3, 2);
    memcpy(data_buf + 10, data+5, data[2]);
    memcpy(data_buf + 10 + data[2], "\r\n", 2);

    memset(data, 0, len);

    memcpy(data, data_buf, data_len);

    return data_len;
}

/*
接收方得到数据：f1 dd 07 23 23 ff ff 41 42 43
    f1 dd : 固定的头部
    07： 之后数据的长度（5-16之间） 
    23 23：对端（发送方）的MADDR
    ff ff: 我的MADDR或ffff(群发)
    41 42 43：发送的数据 
处理后的数据格式：conn_type id_len msg_len id msg

问题：完整的蓝牙数据需要多次读取才能得到，还需要过滤掉前后无用的数据

解决：将读取传入的data缓存到到一个容器中，同时判断是否已经接收到一个完整的蓝牙数据
*/
int app_bt_postRead(char *data, int len)
{
    memcpy(read_buf + read_len, data, len);
    read_len += len;
    memset(data, 0, len);

    if(read_len < 8) 
    {
        log_debug("read_len < 8");
        return 0;
    }

    int i = 0;
    for(i = 0; i < read_len - 7; i++)
    {
        if(memcmp(read_buf + i, head_frame, 2) == 0)
        {

            if(i>0)
            {
                remove_data(i);
            }

            if(read_len < read_buf[2] + 3)
            {
                log_debug("read_len < read_buf[2] + 7");
                return 0;
            }
            
            data[0] = 1;
            data[1] = 2;
            data[2] = read_buf[2] - 4;
            memcpy(data + 3, read_buf + 3, 2);
            memcpy(data + 5, read_buf + 7, data[2]);

            return data[2] + 5;
        }
    }

    if(i > 0)
    {
        log_debug("no effective data");
        remove_data(i);
    }
}

int app_bt_status(Device_t *device)
{
    char *cmd = "AT\r\n";

    write(device->fd, cmd, strlen(cmd));

    return wait_ack(device->fd);
}

int app_bt_setBaudRate(Device_t *device, BT_BaudRate rate)
{
    char data_buf[20];
    snprintf(data_buf, sizeof(data_buf),"AT+BAUD%c\r\n", rate);

    write(device->fd, data_buf, strlen(data_buf));

    return wait_ack(device->fd);
}

int app_bt_rename(Device_t *device, char *name)
{
    char data_buf[20];
    snprintf(data_buf, sizeof(data_buf),"AT+NAME%s\r\n", name);

    write(device->fd, data_buf, strlen(data_buf));

    return wait_ack(device->fd);
}

int app_bt_setNetid(Device_t *device, char *netid)
{
    char data_buf[20];
    snprintf(data_buf, sizeof(data_buf),"AT+NETID%s\r\n", netid);

    write(device->fd, data_buf, strlen(data_buf));

    return wait_ack(device->fd);
}

int app_bt_setMaddr(Device_t *device, char *maddr)
{
    char data_buf[20];
    snprintf(data_buf, sizeof(data_buf),"AT+MADDR%s\r\n", maddr);

    write(device->fd, data_buf, strlen(data_buf));

    return wait_ack(device->fd);
}

int app_bt_reset(Device_t *device)
{
    // 定义指令
    char *cmd = "AT+RESET\r\n";

    // 将指令写入串口文件， 发送给蓝牙
    write(device->fd, cmd, strlen(cmd));

    // 接收ack, 判断是否成功
    return wait_ack(device->fd);
}